<?php


/**
* Шлюз для приема SMS-сообщений и статусов.
*
* @author Владислав В. Костянецкий <bytecoded@gmail.com>
* @link   http://drfreddy.ru/akinoyume/
*/


// Инициализация.

exit;

require_once 'init.php';

$test = 0;

// Считываем входящие параметры.

if ( $test )
{
  ini_set( 'display_errors', 1 );
  error_reporting( E_ALL );

  $sender       = '79236306653';
  $recipient    = '79021103980';
  $message      = 'АД12 СК3';
  $sent_time    = '1349009358';
  $recieve_time = '1349009413';
  
  $md5_calculated = 1;  
  $md5_recieved   = 1;
}
else
{
  $sender       = filter_input( INPUT_POST , 'phone' , FILTER_SANITIZE_STRING );
  $recipient    = filter_input( INPUT_POST , 'to'    , FILTER_SANITIZE_STRING );
  $message      = filter_input( INPUT_POST , 'mes'   , FILTER_SANITIZE_STRING );
  $sent_time    = filter_input( INPUT_POST , 'sent'  , FILTER_SANITIZE_STRING );
  $recieve_time = filter_input( INPUT_POST , 'time'  , FILTER_SANITIZE_STRING );
  
  $md5_calculated = md5( "$sender:$message:$recipient:contra20" );  
  $md5_recieved   = filter_input( INPUT_POST, 'md5', FILTER_SANITIZE_STRING );
}

// Проверяем валидность входящих параметров.

if ( $md5_calculated != $md5_recieved ) exit;

// Записываем SMS в базу данных.

app::$db->execute( 
  
  "INSERT INTO `sms`
    ( `sender`, `recipient`, `message`, `sent_time`, `recieve_time` ) 
    VALUES 
    ( :sender, :recipient, :message, :sent_time, :recieve_time )",
    
  array( 
    'sender'        => $sender,
    'recipient'     => $recipient,
    'message'       => $message,
    'sent_time'     => $sent_time,
    'recieve_time'  => $recieve_time 
  ) 
  
);

$sms_id = app::$db->last_insert_id();

// Пробуем получить билет этого мобильника.

$ticket = app::$db->get( "SELECT * FROM `tickets` WHERE `phone` = ?", array( $sender ) );
$logged = (bool)$ticket;

// Либо авторизация, либо голосования (если авторизация уше прошла).

if ( ! $logged )
{
  // ---------------------------------------- //
  // АВТОРИЗАЦИЯ
  // ---------------------------------------- //
  
  $number = trim( $message );
  
  if ( mb_strlen( $number ) > 7 ) $number = mb_substr( $number, 0, 7 );

  $ticket = app::$db->get( "SELECT * FROM `tickets` WHERE `number` = :number", array( 'number' => $number ) );
  
  if ( $ticket )
  {
    // Авторизация успешна! :-)

    if ( $ticket['phone'] == '' )
    {    
      app::$db->execute( 
        "UPDATE `tickets` SET `phone` = :phone WHERE `id` = :ticket_id",
        array( 
          'phone'     => $sender,
          'ticket_id' => $ticket['id']
        ) 
      );
              
      app::$db->execute( 
        "UPDATE `sms` SET `ticket_id` = :ticket_id, `result` = :result, `type` = 'auth' WHERE `id` = :sms_id",
        array( 
          'ticket_id' => $ticket['id'],
          'result'    => "УСПЕХ (ID билета {$ticket['id']})",
          'sms_id'    => $sms_id
        ) 
      );        
      
      transmitter( $sender, "О, билет $number! Вы можете голосовать :-)" );
    }
    else
    {
      app::$db->execute( 
        "UPDATE `sms` SET `result` = :result, `type` = 'auth' WHERE `id` = :sms_id",
        array( 
          'result' => "ОШИБКА (билет уже за телефоном {$ticket['phone']})",
          'sms_id' => $sms_id,
        )
      );    
      
      transmitter( $sender, "Билет $number уже голосует! Обратитесь, пожалуйста, к волонтерам :-(" );
    }
  }
  else
  {
    // Авторизация неуспешна! :-(
    
    app::$db->execute( 
      "UPDATE `sms` SET `result` = :result, `type` = 'auth' WHERE `id` = :sms_id",
      array( 
        'result' => "ОШИБКА (билет не найден)",
        'sms_id' => $sms_id,
      )
    );
    
    transmitter( $sender, "Билет с номером $number не найден :-(" );
  }
}
else
{
  // ---------------------------------------- //
  // ГОЛОСОВАНИЕ
  // ---------------------------------------- //  

  poll( $ticket, $sms_id, $sender, $message );
}

header( 'HTTP/1.0 200 OK' );
header( 'HTTP/1.1 200 OK' );

header( 'Expires: Mon, 26 Jul 1997 05:00:00 GMT' ); 
header( 'Cache-Control: no-store, no-cache, must-revalidate' ); 
header( 'Cache-Control: post-check=0, pre-check=0', false ); 
header( 'Pragma: no-cache' ); 

print mt_rand( 0, 1000000 );

exit;

function transmitter( $phone, $message )
{
  $elogin    = urlencode('akinoyume' );
  $epassword = urlencode('gecnbcdjb' );
  $ephone    = urlencode( $phone );
  $emessage  = urlencode( $message );
  
  $result = file_get_contents( "https://smsc.ru/sys/send.php?login=$elogin&psw=$epassword&phones=$ephone&mes=$emessage&charset=utf-8" );
  
  app::$db->execute( 
  
    "INSERT INTO `transmitter`
      ( `phone`, `message`, `result`, `sent_time`  ) 
      VALUES 
      ( :phone, :message, :result, UNIX_TIMESTAMP() )",
      
    array( 
      'phone'   => $phone,
      'message' => $message,
      'result'  => $result,
    ) 
  
  );  
}

function remove_spaces( $vote )
{
  while ( substr_count( $vote, '  ' ) )
  {  
    $vote = str_replace( '  ', ' ', $vote );      
  }
  
  return trim( $vote );
}

function poll( $ticket, $sms_id, $sender, $message )
{
  
  // Номера должны разделяться пробелами

  $message  = str_replace(  '.' , ' ', $message );  
  $message  = str_replace(  '.' , ' ', $message );
  $message  = str_replace(  ',' , ' ', $message );
  $message  = str_replace(  '  ', ' ', $message );
  $message  = str_replace(  '  ', ' ', $message );
  
  $polls    = explode( ' ' , $message );
  $votes    = array();

  foreach( $polls as $poll )
  {
    $poll = trim( $poll );
    $data = check_poll( $poll, $message );
    
    if ( ! $data['result'] )
    {
      app::$db->execute( 
        "UPDATE `sms` SET `result` = :result, `ticket_id` = :ticket_id, `type` = 'vote' WHERE `id` = :sms_id",
        array( 
          'ticket_id' => $ticket['id'], 
          'result'    => $data['reason'],
          'sms_id'    => $sms_id,
        )
      );        
      
      transmitter( $sender, $data['message'] );
      
      return;
    }
    
    $votes[ $data['topic_id'] ] = $data['request_id'];
  }
 
  $description = array();
 
  foreach( $votes as $topic_id => $request_id ) 
  {
    do_poll( $ticket['id'], $topic_id, $request_id );
    
    $description[] = "$topic_id = $request_id";
  }
 
  app::$db->execute( 
    "UPDATE `sms` SET `result` = :result, `ticket_id` = :ticket_id, `type` = 'vote' WHERE `id` = :sms_id",
    array( 
      'ticket_id' => $ticket['id'],
      'result'    => 'УСПЕХ (' . implode( ', ' , $description ) . ')',
      'sms_id'    => $sms_id,
    )
  );                          
       
  transmitter( $sender, "Голос ($message) принят! Пиши еще :-)" );
}

function check_poll( $vote, $message )
{
  
  // Проверяем наличие корректного номера формата СК12
 
  if (preg_match('/([а-яА-Я]{2})(\d{2})/', $message, $matches)!=1)
  {    
    return array( 
      'result'  => false,
      'reason'  => 'ОШИБКА (некорректные номера)',
      'message' => "Голос '$message' не принят! Не нашел номеров участников :-(",
    );
  }
  
  $card = $matches[0];
  $voting_number = $matches[1];
  
  // Проверяем, что существует номинация с заданным номером:
    
  $topic = app::$db->get( "SELECT `id`, `card` FROM `topics` WHERE `card` = ?", array( $card ) );
        
  if ( ! $topic )
  {
    $message = str_replace( ',', ', ', $message );    
  
    if ( mb_strlen( $message ) > 10 ) $vote = mb_substr( $vote, 0, 10 ) . ' (...)';
  
    return array( 
      'result'  => false,
      'reason'  => "ОШИБКА (номинация $card не найдена)",
      'message' => "Голос '$message' не принят! Нет номинации {$card} :-(",
    );  
  }
  
  // Проверяем, что существует участник с таким номером:
  
  $request = app::$db->get( "SELECT `id`, `code` FROM `requests` WHERE `topic_id` = :topic_id AND `voting_number` = :voting_number",
    array( 
      'topic_id' => $topic['id'],
      'voting_number' => $voting_number,
    )
  );
          
  if ( ! $request )
  {    
  
    if ( mb_strlen( $message ) > 10 ) $vote = mb_substr( $vote, 0, 10 ) . ' (...)';
  
    return array( 
      'result'  => false,
      'reason'  => "ОШИБКА (заявка с номинацией $card и номером $voting_number не найдена)",
      'message' => "Голос '$message' не принят! Нет {$voting_number}-го участника в номинации {$card} :-(",
    );  
  }

  // Все в порядке!
  
  return array( 
    'result'        => true,
    'request_id'    => $request['id'],    
    'topic_id'      => $topic['id'],
  );      
}

function do_poll( $ticket_id, $topic_id, $request_id )
{
  // Удаляем возможный голос от билета в номинации:

  app::$db->execute(
    "DELETE FROM `votes` WHERE `ticket_id` = :ticket_id AND `topic_id` = :topic_id",
    array( 
      'ticket_id'     => $ticket_id,
      'topic_id'      => $topic_id, 
    )
  );    
            
  // Регистрируем новый голос в номинации:
            
  app::$db->execute( "
    INSERT INTO `votes`
    ( `type`, `ticket_id`, `topic_id`, `request_id` )
    VALUES
    ( 'sms', :ticket_id, :topic_id, :request_id )",
              
    array(      
      'ticket_id'     => $ticket_id,
      'topic_id'      => $topic_id,              
      'request_id'    => $request_id,      
    )
  );          
}